package com.ofek.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.ofek.applicationbase.broadcast.ReflectionUtils;



public class DebugUtils {

	private static final ExecutorService es = Executors.newSingleThreadExecutor();

	public static void printObject(final Object obj) {
		System.out.println(toString(obj));
	}
	public static String toString(final Object obj) {
		return toString(0,obj,new HashSet<>());
	}

	private static String toString(final int level,final Object obj,final HashSet<Object> sofar) {
		final Class<? extends Object> class1 = obj.getClass();
		if (ReflectionUtils.isPrimitive(obj) || ReflectionUtils.isCollection(obj) || class1.isAnnotationPresent(DebugBlock.class)) 
			return obj.toString();
		if (sofar.contains(obj)) 
			return "Repeating";
		sofar.add(obj);
		final StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(obj);
		stringBuilder.append('\n');

		for (final Field f : class1.getDeclaredFields()) {
			if (Modifier.isStatic(f.getModifiers()) || f.getName().equals("this$0")) continue;
			//if (!f.getDeclaringClass().isPrimitive()) continue;
			final boolean accessible = f.isAccessible();
			f.setAccessible(true);
			for (int i = 0 ; i < level+1 ; i++) 
				stringBuilder.append("\t");
			stringBuilder.append(f.getName());
			stringBuilder.append(" : ");
			try {
				stringBuilder.append(toString(level+1,f.get(obj),sofar));
			} catch (final Exception e) {
				stringBuilder.append("Couldnt evluate get on this field");
			}
			stringBuilder.append('\n');
			f.setAccessible(accessible);
		}
		return stringBuilder.toString();
	}

}
